home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / cmdparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-16  |  9.1 KB  |  452 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Improved error handling by Brian Boesch of Stanford University
  7.  * Feb '91 - Bill Simpson
  8.  *        bit16cmd for PPP
  9.  * Mar '91 - Glenn McGregor
  10.  *        handle string escaped sequences
  11.  */
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include <conio.h>
  15. #include "global.h"
  16. #include "config.h"
  17. #include "proc.h"
  18. #include "cmdparse.h"
  19. #include "session.h"
  20.  
  21. void dohelper __ARGS((char *title,struct cmds *cmdp,char *stopstr,char *filename,char *search));
  22.  
  23. struct boolcmd {
  24.     char *str;    /* Token */
  25.     int val;    /* Value */
  26. };
  27.  
  28. static struct boolcmd Boolcmds[] = {
  29.     "y",        1,    /* Synonyms for "true" */
  30.     "yes",        1,
  31.     "true",        1,
  32.     "on",        1,
  33.     "1",        1,
  34.     "set",        1,
  35.     "enable",    1,
  36.  
  37.     "n",        0,    /* Synonyms for "false" */
  38.     "no",        0,
  39.     "false",    0,
  40.     "off",        0,
  41.     "0",        0,
  42.     "clear",    0,
  43.     "disable",    0,
  44.     NULLCHAR
  45. };
  46.  
  47. static char *stringparse __ARGS((char *line));
  48.  
  49. static char *
  50. stringparse(line)
  51. char *line;
  52. {
  53.     register char *cp = line;
  54.     unsigned long num;
  55.  
  56.     while ( *line != '\0' && *line != '\"' ) {
  57.         if ( *line == '\\' ) {
  58.             line++;
  59.             switch ( *line++ ) {
  60.             case 'n':
  61.                 *cp++ = '\n';
  62.                 break;
  63.             case 't':
  64.                 *cp++ = '\t';
  65.                 break;
  66.             case 'v':
  67.                 *cp++ = '\v';
  68.                 break;
  69.             case 'b':
  70.                 *cp++ = '\b';
  71.                 break;
  72.             case 'r':
  73.                 *cp++ = '\r';
  74.                 break;
  75.             case 'f':
  76.                 *cp++ = '\f';
  77.                 break;
  78. #ifdef TNOS_68K
  79.             case 'l':
  80.                 *cp++ = '\l';
  81.                 break;
  82. #endif
  83. #ifndef UNIX
  84.             case 'a':
  85.                 *cp++ = '\a';
  86.                 break;
  87. #endif
  88.             case '\\':
  89.                 *cp++ = '\\';
  90.                 break;
  91.             case '\?':
  92.                 *cp++ = '\?';
  93.                 break;
  94.             case '\'':
  95.                 *cp++ = '\'';
  96.                 break;
  97.             case '\"':
  98.                 *cp++ = '\"';
  99.                 break;
  100.             case 'x':
  101.                 num = strtoul( --line, &line, 16 );
  102.                 *cp++ = (char) num;
  103.                 break;
  104.             case '0':
  105.             case '1':
  106.             case '2':
  107.             case '3':
  108.             case '4':
  109.             case '5':
  110.             case '6':
  111.             case '7':
  112.                 num = strtoul( --line, &line, 8 );
  113.                 *cp++ = (char) num;
  114.                 break;
  115.             case '\0':
  116.                 return NULLCHAR;
  117.             default:
  118.                 *cp++ = *(line - 1);
  119.                 break;
  120.             };
  121.         } else {
  122.             *cp++ = *line++;
  123.         }
  124.     }
  125.  
  126.     if ( *line == '\"' )
  127.         line++;     /* skip final quote */
  128.     *cp = '\0';        /* terminate string */
  129.     return line;
  130. }
  131.  
  132. #ifdef LOCK
  133. int Kblocked;
  134. char *Kbpasswd;
  135. #endif
  136.  
  137. int
  138. cmdparse(cmds,line,p)
  139. struct cmds cmds[];
  140. register char *line;
  141. void *p;
  142. {
  143. struct cmds *cmdp;
  144. char *argv[NARG],*cp;
  145. char **pargv;
  146. int argc,i, isconv;
  147.  
  148.     /* Remove cr/lf */
  149.     rip(line);
  150.  
  151.     for(argc = 0;argc < NARG;argc++)
  152.         argv[argc] = NULLCHAR;
  153.  
  154.     for(argc = 0;argc < NARG;){
  155.         register int qflag = FALSE;
  156.  
  157.         /* Skip leading white space */
  158.         while(*line == ' ' || *line == '\t')
  159.             line++;
  160.         if(*line == '\0')
  161.             break;
  162.         /* return if comment character first non-white */
  163.         if ( argc == 0  &&  *line == '#' )
  164.             return 0;
  165.         /* Check for quoted token */
  166.         if(*line == '"'){
  167.             line++;    /* Suppress quote */
  168.             qflag = TRUE;
  169.         }
  170.         argv[argc++] = line;    /* Beginning of token */
  171.  
  172.         if(qflag){
  173.             /* Find terminating delimiter */
  174.             if((line = stringparse(line)) == NULLCHAR){
  175.                 return -1;
  176.             }
  177.         } else {
  178.             /* Find space or tab. If not present,
  179.              * then we've already found the last
  180.              * token.
  181.              */
  182.             if((cp = strpbrk(line," \t")) == NULLCHAR)
  183.                 break;
  184.             *cp++ = '\0';
  185.             line = cp;
  186.         }
  187.     }
  188.     if (argc < 1) {        /* empty command line */
  189.         argc = 1;
  190.         argv[0] = "";
  191.     }
  192.  
  193. #ifdef LOCK
  194.     /* Check to see if this is the Command session.
  195.      * If so, check to see if the keyboard is locked
  196.      * Added 12/12/91 WG7J
  197.      * Also, skips this check if it is a command from the AT queue 12/16/93 KO4KS
  198.      */
  199.     if((Curproc->input == Command->input) && strcmp ("AT handler", Curproc->name))
  200.         if(Kblocked) { /*check argv[0] for password!*/
  201.             if(stricmp(argv[0],Kbpasswd)) {
  202.                 tputs("\nKeyboard remains locked\n");
  203.                 return 0;
  204.             }
  205.             Command->ttystate.echo = 1; /* turn character echo back on ! */
  206.             Kblocked=0;   /* correct password, so unlock */
  207.             tputc ('\n');
  208.             return 0;
  209.         }
  210. #endif
  211.  
  212.     /* Look up command in table; prefix matches are OK */
  213.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  214.         if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0)
  215.             break;
  216.     }
  217.     if(cmdp->name == NULLCHAR) {
  218.         if(cmdp->argc_errmsg != NULLCHAR)
  219.             tprintf("%s\n",cmdp->argc_errmsg);
  220.         return -1;
  221.     } else {
  222.         if(argc < cmdp->argcmin) {
  223.             /* Insufficient arguments */
  224.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  225.             return -1;
  226.         } else {
  227.             if(cmdp->stksize == 0){
  228.                 return (*cmdp->func)(argc,argv,p);
  229.             } else {
  230.                 /* Make private copy of argv and args,
  231.                  * spawn off subprocess and return.
  232.                  */
  233.                 isconv = (!stricmp (cmdp->name, "conference")
  234.                     || !stricmp (cmdp->name, "rlogin")
  235.                     || !stricmp (cmdp->name, "quote")
  236.                     || !stricmp (cmdp->name, "tutor")
  237.                     || !stricmp (cmdp->name, "info")
  238.                     || !stricmp (cmdp->name, "news"));
  239.                 pargv = (char **)callocw((isconv) ? 3 : argc,sizeof(char *));
  240.                 for(i=0;i<argc;i++)
  241.                     pargv[i] = strdup(argv[i]);
  242.                 newproc(cmdp->name,cmdp->stksize,
  243.                 (void (*)())cmdp->func,(isconv) ? 3 : argc,pargv,p,1);
  244.                 return(0);
  245.             }
  246.         }
  247.     }
  248. }
  249.  
  250. /* Call a subcommand based on the first token in an already-parsed line */
  251. int
  252. subcmd(tab,argc,argv,p)
  253. struct cmds tab[];
  254. int argc;
  255. char *argv[];
  256. void *p;
  257. {
  258.     register struct cmds *cmdp;
  259.     char **pargv;
  260.     int found = 0;
  261.     int i;
  262.  
  263.     /* Strip off first token and pass rest of line to subcommand */
  264.     if (argc < 2) {
  265.         if (argc < 1)
  266.             tprintf("SUBCMD - Don't know what to do?\n");
  267.         else
  268.             tprintf("\"%s\" - takes at least one argument\n",argv[0]);
  269.         return -1;
  270.     }
  271.     argc--;
  272.     argv++;
  273.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  274.         if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0){
  275.             found = 1;
  276.             break;
  277.         }
  278.     }
  279.     if(!found){
  280. #ifdef nope
  281.         tprintf("valid subcommands:");
  282.         for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
  283.             if(tprintf(" %s",cmdp->name) == EOF)
  284.                 return -1;
  285.         tprintf("\n");
  286. #endif
  287.         dohelper ("valid subcommands:\n", tab, NULLCHAR, NULLCHAR, NULLCHAR);
  288.         return -1;
  289.     }
  290.     if(argc < cmdp->argcmin){
  291.         if(cmdp->argc_errmsg != NULLCHAR)
  292.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  293.         return -1;
  294.     }
  295.     if(cmdp->stksize == 0){
  296.         return (*cmdp->func)(argc,argv,p);
  297.     } else {
  298.         /* Make private copy of argv and args */
  299.         pargv = (char **)callocw(argc,sizeof(char *));
  300.         for(i=0;i<argc;i++)
  301.             pargv[i] = strdup(argv[i]);
  302.         newproc(cmdp->name,cmdp->stksize,
  303.          (void (*)())cmdp->func,argc,pargv,p,1);
  304.         return(0);
  305.     }
  306. }
  307.  
  308. /* Subroutine for setting and displaying boolean flags */
  309. int
  310. setbool(var,label,argc,argv)
  311. int *var;
  312. char *label;
  313. int argc;
  314. char *argv[];
  315. {
  316.     struct boolcmd *bc;
  317.  
  318.     if(argc < 2){
  319.         tprintf("%s: %s\n",label,*var ? "on":"off");
  320.         return 1;
  321.     }
  322.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  323.         if(strcmpi(argv[1],bc->str) == 0){
  324.             *var = bc->val;
  325.             return 0;
  326.         }
  327.     }
  328.     tprintf("Valid options:");
  329.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  330.         if(tprintf(" %s",bc->str) == EOF)
  331.             return 1;
  332.     tprintf("\n");
  333.     return 1;
  334. }
  335.  
  336.  
  337. /* Subroutine for setting and displaying bit values */
  338. int
  339. bit16cmd(bits,mask,label,argc,argv)
  340. int16 *bits;
  341. int16 mask;
  342. char *label;
  343. int argc;
  344. char *argv[];
  345. {
  346.     int doing = (*bits & mask);
  347.     int result = setbool( &doing, label, argc, argv );
  348.  
  349.     if ( !result ) {
  350.         if ( doing )
  351.             *bits |= mask;
  352.         else
  353.             *bits &= ~mask;
  354.     }
  355.     return result;
  356. }
  357.  
  358.  
  359. /* Subroutine for setting and displaying long variables */
  360. int
  361. setlong(var,label,argc,argv)
  362. long *var;
  363. char *label;
  364. int argc;
  365. char *argv[];
  366. {
  367.     if(argc < 2){
  368.         tprintf("%s: %ld\n",label,*var);
  369.         return 1;
  370.     } else {
  371.         *var = atol(argv[1]);
  372.         return 0;
  373.     }
  374.  
  375. }
  376. /* Subroutine for setting and displaying short variables */
  377. int
  378. setshort(var,label,argc,argv)
  379. unsigned short *var;
  380. char *label;
  381. int argc;
  382. char *argv[];
  383. {
  384.     if(argc < 2){
  385.         tprintf("%s: %u\n",label,*var);
  386.         return 1;
  387.     } else {
  388.         *var = atoi(argv[1]);
  389.         return 0;
  390.     }
  391. }
  392. /* Subroutine for setting and displaying integer variables */
  393. int
  394. setint(var,label,argc,argv)
  395. int *var;
  396. char *label;
  397. int argc;
  398. char *argv[];
  399. {
  400.     if(argc < 2){
  401.         tprintf("%s: %i\n",label,*var);
  402.         return 1;
  403.     } else {
  404.         *var = atoi(argv[1]);
  405.         return 0;
  406.     }
  407.  
  408. }
  409.  
  410. /* Subroutine for setting and displaying unsigned integer variables */
  411. int
  412. setuns(var,label,argc,argv)
  413. unsigned *var;
  414. char *label;
  415. int argc;
  416. char *argv[];
  417. {
  418.     if(argc < 2){
  419.         tprintf("%s: %u\n",label,*var);
  420.         return 1;
  421.     } else {
  422.         *var = atoi(argv[1]);
  423.         return 0;
  424.     }
  425. }
  426.  
  427. /* Subroutine for setting and displaying int variables (with range check) */
  428. int
  429. setintrc(var, label, argc, argv, minval, maxval)
  430. int16 *var;
  431. char *label;
  432. int argc;
  433. char *argv[];
  434. int minval;
  435. int16 maxval;
  436. {
  437.     int tmp;
  438.  
  439.     if (argc < 2)
  440.         tprintf("%s: %u\n", label, *var);
  441.     else {
  442.         tmp = atoi(argv[1]);
  443.         if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
  444.             tprintf("%s must be %i..%i\n", label, minval, maxval);
  445.             return 1;
  446.         }
  447.         *var = (int16)tmp;
  448.     }
  449.     return 0;
  450. }
  451.  
  452.